"""
实现了一个自动依赖库管理工具，主要功能包括：
依赖版本对比：
比较 version_library_comparisons.txt 和 requirements.txt 两个文件
version_library_comparisons.txt作为版本对比的参考标准
requirements.txt是当前项目依赖文件，实际安装依赖的依据文件
当两个文件内容相同时，表示依赖未更新，跳过安装
当两个文件内容不同时，表示有依赖更新，触发自动安装流程
安装完成后，会将 requirements.txt 的内容写入 version_library_comparisons.txt
确保下次对比时以最新版本为基准
智能安装机制：
1.当检测到依赖更新时，逐个安装依赖库
2.单个库安装失败不会影响其他库的安装
3.记录并报告安装失败的库
"""
import os
import chardet
import subprocess
import sys
from common.setting import ensure_path_sep
from utils.logging_tool.log_control import INFO
from utils import config

os.system("pip3 install chardet")


class InstallRequirements:
    """ 自动识别安装最新的依赖库 """

    def __init__(self):
        self.version_library_comparisons_path = ensure_path_sep("\\utils\\other_tools\\install_tool\\") \
                                                + "version_library_comparisons.txt"
        # 修改为正确的路径，使用当前文件所在目录
        self.requirements_path = os.path.dirname(os.path.abspath(__file__)) \
                                 + os.sep + "requirements.txt"

        self.mirror_url = config.mirror_source
        # 初始化时，获取最新的版本库

        # os.system("pip freeze > {0}".format(self.requirements_path))

    def read_version_library_comparisons_txt(self):
        """
        获取版本比对默认的文件
        @return:
        """
        with open(self.version_library_comparisons_path, 'r', encoding="utf-8") as file:
            return file.read().strip(' ')

    @classmethod
    def check_charset(cls, file_path):
        """获取文件的字符集"""
        with open(file_path, "rb") as file:
            data = file.read(4)
            charset = chardet.detect(data)['encoding']
        return charset

    def read_requirements(self):
        """获取安装文件"""
        file_data = ""
        with open(
                self.requirements_path,
                'r',
                encoding=self.check_charset(self.requirements_path)
        ) as file:

            for line in file:
                if "[0m" in line:
                    line = line.replace("[0m", "")
                file_data += line

        with open(
                self.requirements_path,
                "w",
                encoding=self.check_charset(self.requirements_path)
        ) as file:
            file.write(file_data)

        return file_data

    def text_comparison(self):
        """
        版本库比对
        @return:
        """
        read_version_library_comparisons_txt = self.read_version_library_comparisons_txt()
        read_requirements = self.read_requirements()
        if read_version_library_comparisons_txt == read_requirements:
            INFO.logger.info("程序中未检查到更新版本库，已为您跳过自动安装库")
        # 程序中如出现不同的文件，则安装
        else:
            INFO.logger.info("程序中检测到您更新了依赖库，已为您自动安装")
            failed_packages = self.install_requirements_individually()
            if failed_packages:
                INFO.logger.warning(f"以下库安装失败: {', '.join(failed_packages)}")
            else:
                INFO.logger.info("所有依赖库安装成功")
            with open(self.version_library_comparisons_path, "w",
                      encoding=self.check_charset(self.requirements_path)) as file:
                file.write(read_requirements)

    def install_requirements_individually(self):
        """逐个安装依赖库并记录失败的库"""
        failed_packages = []
        with open(self.requirements_path, 'r', encoding=self.check_charset(self.requirements_path)) as file:
            for line in file:
                line = line.strip()
                if line and not line.startswith('#'):
                    # 跳过特殊字符行
                    if "[0m" in line:
                        line = line.replace("[0m", "")
                    try:
                        # 使用 subprocess 替代 os.system 以获得更好的错误处理
                        result = subprocess.run(
                            [sys.executable, "-m", "pip", "install", line],
                            capture_output=True,
                            text=True,
                            timeout=300  # 5分钟超时
                        )
                        if result.returncode != 0:
                            failed_packages.append(line)
                            INFO.logger.warning(f"安装失败: {line}, 错误: {result.stderr}")
                        else:
                            INFO.logger.info(f"安装成功: {line}")
                    except subprocess.TimeoutExpired:
                        failed_packages.append(line)
                        INFO.logger.warning(f"安装超时: {line}")
                    except Exception as e:
                        failed_packages.append(line)
                        INFO.logger.warning(f"安装异常: {line}, 错误: {str(e)}")
        return failed_packages


if __name__ == '__main__':
    InstallRequirements().text_comparison()
